/*******************************************************************************
 * Copyright (c) 2009-2011 ETCORE Labs. All rights reserved. 
 * 
 * This software is the confidential and proprietary information of ETCORE Labs.
 * You shall not disclose such confidential information and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with ETCORE Labs. 
 * 
 * Support can be obtained from support forums at:  http://www.etcore.com/
 * /
 *******************************************************************************/
package etcore.webapp.grouptalk.common.action;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import etcore.webapp.grouptalk.common.config.Config;
import etcore.webapp.grouptalk.common.config.Layout;
import etcore.webapp.grouptalk.common.config.MessageNamespaces;
import etcore.webapp.grouptalk.common.config.Messages;
import etcore.webapp.grouptalk.common.config.PageConstants;
import etcore.webapp.grouptalk.common.object.Directory;
import etcore.webapp.grouptalk.common.object.Group;
import etcore.webapp.grouptalk.common.object.Topic;
import etcore.webapp.grouptalk.common.service.CommentService;
import etcore.webapp.grouptalk.common.service.DirectoryService;
import etcore.webapp.grouptalk.common.service.GroupService;
import etcore.webapp.grouptalk.common.service.MessageService;
import etcore.webapp.grouptalk.common.service.TopicService;

 

import etcore.webapp.grouptalk.user.object.User;
import etcore.webapp.grouptalk.user.service.FocusService;
import etcore.webapp.grouptalk.user.service.MemberService;
import etcore.webapp.grouptalk.util.Symbols;

/**
 * This action is an abstract action which defines methods to be implemented
 * 
 * @author ETCORE GroupTalk Developers
 * 
 */
public abstract class AbstractAction extends HttpServlet {

	private static final long serialVersionUID = 8460401643573938491L;

	public abstract boolean enablePostLoad();

	/**
	 * read common labels and attributes
	 * 
	 * @param request
	 * @param response
	 * @param context
	 */
	public static void buildCommonContextAndAttributes(
			HttpServletRequest request, HttpServletResponse response,
			Map<String,String> context) {
		if (context == null || request == null)
			return;
		HttpSession session = request.getSession(true);
		if (!context.containsKey(Config.POSTFIX)) {

			// load config
			Enumeration<Object> e = Config.getConfig().keys();
			while (e.hasMoreElements()) {
			String key = (String) e.nextElement();
			context.put(key, Config.getConfig().getProperty(key));
			}
			// load layout
			Enumeration<Object> e2 = Layout.getLayout().keys();
			while (e2.hasMoreElements()) {
			String key = (String) e2.nextElement();
			context.put(key, Layout.getLayout().getProperty(key));
			}
			String postfix = (String) context.get(Config.POSTFIX);
			if (postfix == null)
				postfix = Config.ACTION_POSTFIX;
			context.put(Config.POSTFIX, postfix);

			// load labels
			buildMessages(MessageNamespaces.COMMON,request,context);
			
			
			
			context.put(Messages.LANG_EN,
					Messages.getELabel(Messages.TEXT_LANG));
			context.put(Messages.LANG_LOCAL,
					Messages.getLabel(Messages.TEXT_LANG));

			boolean isadmin = false, notLogged = true;
			User user = (User) session.getAttribute(Messages.SESSION_USER);
			MemberService memberService = new MemberService();
			if (user != null && memberService.isSysAdmin(user.getUserName())) {
				isadmin = true;
			}
			request.setAttribute(PageConstants.ISADMIN, isadmin);
			if (user != null)
				notLogged = false;
			request.setAttribute(PageConstants.NOTLOGGED, notLogged);
		}
	}
	private static void buildMessages(String namespace,
			HttpServletRequest request ,
			Map<String,String> context) {
		if (context == null || request == null||namespace==null)
			return;	
		HttpSession session = request.getSession(true);
		String lang = (String) session.getAttribute(Messages.LANG);
		if (Messages.LANG_EN.equals(lang))
			context.putAll(Messages.getEMessages().get(namespace));
		else if (Messages.LANG_LOCAL.equals(lang))
			context.putAll(Messages.getMessages().get(namespace));
		else if (request.getLocale().getLanguage()
				.equals(Config.getProperty(Config.LOCAL_LANG)))

			context.putAll(Messages.getMessages().get(namespace));
		else if(Messages.LANG_LOCAL.equals( Config.getConfig().getProperty(Config.DEFAULT_LANG)))
			context.putAll(Messages.getMessages().get(namespace));
		else if(Messages.LANG_EN.equals( Config.getConfig().getProperty(Config.DEFAULT_LANG)))
			context.putAll(Messages.getEMessages().get(namespace));
	}
	public static void postLoadData(HttpServletRequest request,
			HttpServletResponse response, Map<String,String> context) {
		if (context == null || request == null)
			return;
		getDirectories(request, 1);
		getDirectories(request, 2);
		getDirectories(request, 3);
		getDirectories(request, 11);
		getDirectories(request, 22);
		//getNavGroups(request);
		getMyProfile(request);

	}

	private static void getDirectories(HttpServletRequest request, int platform) {
		HttpSession session = request.getSession(true);
		String lang = (String) session.getAttribute(Messages.LANG);

		List<Group> rootGroups = null;
		DirectoryService directoryService = new DirectoryService();
		GroupService groupService = new GroupService();

		int parent = 0;
		if (platform == 1) {

			parent = -1;

			if (Messages.LANG_EN.equals(lang)) {
				rootGroups = groupService.findEnglishGroupsByNotInDirectories(
						new Integer(1), new Integer(0), parent);
			} else {
				rootGroups = groupService.findLocalGroupsByNotInDirectories(
						new Integer(1), new Integer(0), parent);
			}

		} else if (2 == platform) {
			parent = -2;
			if (Messages.LANG_EN.equals(lang)) {
				rootGroups = groupService.findEnglishGroupsByNotInDirectories(
						new Integer(2), new Integer(0), parent);
			} else {
				rootGroups = groupService.findLocalGroupsByNotInDirectories(
						new Integer(2), new Integer(0), parent);
			}

		} else if (3 == platform) {
			parent = -3;
			if (Messages.LANG_EN.equals(lang)) {
				rootGroups = groupService.findEnglishGroupsByNotInDirectories(
						new Integer(3), parent);
			} else {
				rootGroups = groupService.findLocalGroupsByNotInDirectories(
						new Integer(3), parent);
			}

		} else if (11 == platform) {
			parent = -11;
			if (Messages.LANG_EN.equals(lang)) {
				rootGroups = groupService.findEnglishGroupsByNotInDirectories(
						new Integer(1), new Integer(1), parent);
			} else {
				rootGroups = groupService.findLocalGroupsByNotInDirectories(
						new Integer(1), new Integer(1), parent);
			}

		} else if (22 == platform) {
			parent = -22;
			if (Messages.LANG_EN.equals(lang)) {
				rootGroups = groupService.findEnglishGroupsByNotInDirectories(
						new Integer(2), new Integer(1), parent);
			} else {
				rootGroups = groupService.findLocalGroupsByNotInDirectories(
						new Integer(2), new Integer(1), parent);
			}

		}

		request.setAttribute("rootGroups" + platform, rootGroups);
		request.setAttribute("rootGroups" + platform + "Size",
				rootGroups.size());
		List<Directory> directories = null;
		if (Messages.LANG_EN.equals(lang)) {
			directories = directoryService
					.findEnglishDirectoriesByParent(parent);
		} else {
			directories = directoryService.findLocalDirectoriesByParent(parent);
		}

		for (Directory directory : directories) {
			List<Group> groups = null;
			if (Messages.LANG_EN.equals(lang)) {
				groups = groupService.findEnglishGroupsByDid(directory.getId());
			} else {
				groups = groupService.findLocalGroupsByDid(directory.getId());
			}
			request.setAttribute(directory.getId() + PageConstants.GROUPS,
					groups);

		}

		request.setAttribute("directories" + platform, directories);

	}

	private static void getMyProfile(HttpServletRequest request) {
		HttpSession session = request.getSession(true);
		User user = (User) session.getAttribute(Messages.SESSION_USER);
		if (user == null)
			return;
		long myFollowingCount = 0, myFollowersCount = 0, myGroupsCount = 0, myFavouriteCount = 0, myMessagesCount = 0,myCommentsCount=0;
		FocusService focusService = new FocusService();
		MessageService msgService = new MessageService();
		GroupService groupService = new GroupService();
		CommentService commentService=new CommentService();
		myFollowingCount = focusService.findSizeByProperty("fromUser",
				user.getUserName());
		myFollowersCount = focusService.findSizeByProperty("toUser",
				user.getUserName());
		myGroupsCount = groupService.findFavouriteGroupsSize(
				user.getUserName(), 2);
		myFavouriteCount = msgService.findSizeOfFavouriteMessages(user
				.getUserName());
		myMessagesCount = msgService.findSizeOfPublicMessages(PageConstants.USERNAME,
				user.getUserName());
		myCommentsCount=commentService.findPublicCommentsSizeByProperty(PageConstants.USERNAME, user.getUserName());
		request.setAttribute("myFollowingCount", myFollowingCount);
		request.setAttribute("myFollowersCount", myFollowersCount);
		request.setAttribute("myGroupsCount", myGroupsCount);
		request.setAttribute("myFavouriteCount", myFavouriteCount);
		request.setAttribute("myMessagesCount", myMessagesCount);
		request.setAttribute("myCommentsCount", myCommentsCount);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static void getNavGroups(HttpServletRequest request) {
		int groupNum = 5;
		int msgCount = 5;
		String msgCountStr = request.getParameter("msgCount");
		if (msgCountStr != null && !Symbols.BLANK.equals(msgCountStr)) {
			msgCount = Integer.parseInt(msgCountStr);
		}
		List<Group> platform1NavGroups = null;
		List<Group> platform2NavGroups = null;
		TopicService topicService = new TopicService();
		MessageService msgService = new MessageService();
		GroupService groupService = new GroupService();
		HttpSession session = request.getSession(true);
		String lang = (String) session.getAttribute(Messages.LANG);
		if (Messages.LANG_EN.equals(lang)) {
			platform1NavGroups = groupService.findBy3Properties(
					PageConstants.OPEN, new Integer(1), Messages.LANG_EN,
					new Integer(1), PageConstants.NAV, new Integer(1), 0,
					groupNum);
			platform2NavGroups = groupService.findBy3Properties(
					PageConstants.OPEN, new Integer(2), Messages.LANG_EN,
					new Integer(1), PageConstants.NAV, new Integer(1), 0,
					groupNum);

		} else {
			platform1NavGroups = groupService.findBy3Properties(
					PageConstants.OPEN, new Integer(1), Messages.LANG_LOCAL,
					new Integer(1), PageConstants.NAV, new Integer(1), 0,
					groupNum);
			platform2NavGroups = groupService.findBy3Properties(
					PageConstants.OPEN, new Integer(2), Messages.LANG_LOCAL,
					new Integer(1), PageConstants.NAV, new Integer(1), 0,
					groupNum);

		}
		Map topicMap = new HashMap<Integer, String>();
		for (Group group : platform1NavGroups) {

			List<Topic> topics = topicService.findByProperty(PageConstants.GID,
					new Integer(group.getId()));
			request.setAttribute(group.getId() + PageConstants.TOPICS, topics);
			for (Topic topic : topics) {
				topicMap.put(topic.getId(), topic.getName());
			}

			List msgs = msgService.findTopByDaysAndGid(new Integer(2000),
					group.getId(), 0, msgCount);
			request.setAttribute(group.getId() + PageConstants.MSGS, msgs);

		}
		for (Group group : platform2NavGroups) {

			List<Topic> topics = topicService.findByProperty(PageConstants.GID,
					new Integer(group.getId()));
			request.setAttribute(group.getId() + PageConstants.TOPICS, topics);
			for (Topic topic : topics) {
				topicMap.put(topic.getId(), topic.getName());
			}

			List msgs = msgService.findTopByDaysAndGid(new Integer(2000),
					group.getId(), 0, msgCount);
			request.setAttribute(group.getId() + PageConstants.MSGS, msgs);

		}
		request.setAttribute(PageConstants.PAGE_VARIABLE_PLATFORM1NAVGROUPS,
				platform1NavGroups);
		request.setAttribute(PageConstants.PAGE_VARIABLE_PLATFORM2NAVGROUPS,
				platform2NavGroups);
		request.setAttribute(PageConstants.NAV_TOPIC_MAP, topicMap);

	}

	/**
	 * 
	 * @param request
	 * @return TODO
	 */
	public abstract List<String> getNamespacesOfMessages(HttpServletRequest request);
	/**
	 * do execution according to validation result
	 * 
	 * @param validationResult
	 * @param request
	 * @param response
	 */
	public abstract void execute(int validationResult,
			HttpServletRequest request, HttpServletResponse response);

	/**
	 * get forward page according to validation result
	 * 
	 * @param validationResult
	 * @return
	 */
	public abstract String getForward(HttpServletRequest request,
			int validationResult);

	/**
	 * 
	 * 
	 * @param validationResult
	 * @return
	 */
	public abstract String getRedirect(HttpServletRequest request,
			int validationResult);

	/**
	 * check if go forward
	 * 
	 * @param validationResult
	 * @return
	 */
	public abstract boolean isForward(int validationResult);

	protected void service(HttpServletRequest request,
			HttpServletResponse response) {

		// build common context
		Map<String,String> context = new HashMap<String,String>();

		buildCommonContextAndAttributes(request, response, context);

		if (!enablePostLoad())
			postLoadData(request, response, context);
		// validation
		int validationResult = validate(request, response);
		
		
		List<String> namespaces=getNamespacesOfMessages(request);
		if(namespaces!=null){
			for(String namespace:namespaces){
				buildMessages(namespace,request,context);
			}
		}
		request.setAttribute(Messages.CONTEXT, context);
		// execution
		execute(validationResult, request, response);

		if (enablePostLoad())
			postLoadData(request, response, context);

		
		// jump
		try {
			if (isForward(validationResult)) {
				String forwardPage = getForward(request, validationResult);
				try{
				request.getRequestDispatcher(forwardPage).forward(request,
						response);
				}catch(Exception e){
					e.printStackTrace();
				}

			} else {
				String redirectPage = getRedirect(request, validationResult);
				response.sendRedirect(redirectPage);
			}
		} catch (Exception e) {
			e.printStackTrace();

		}

	}

	/**
	 * validate the request
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	public abstract int validate(HttpServletRequest request,
			HttpServletResponse response);

}
